package org.softmed.rest.admin.aop.manager;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.softmed.action.Action;
import org.softmed.action.builder.ActionCreator;
import org.softmed.action.manager.ActionCache;
import org.softmed.action.manager.ActionManager;
import org.softmed.filehandling.FileUtil;
import org.softmed.rest.config.Handler;
import org.softmed.rest.server.core.handler.HandlerProcessParameters;

import com.google.inject.Inject;

public class CustomActionManager implements ActionManager {

	@Inject
	AOPManager aopManager;

	@Inject
	ActionCreator actionCreator;

	Map<String, ActionCache> actionCache = new HashMap<String, ActionCache>();

	FileUtil util = new FileUtil();

	public Action getAction(String xmlDescription, Object... objects)
			throws Throwable {
		Handler handler = (Handler) objects[0];
		HandlerProcessParameters parameters = (HandlerProcessParameters) objects[1];
		String id = buildID(handler, parameters);
		Action clone = null;
		ActionCache cache = actionCache.get(id);

		File file = util.getFile(xmlDescription);

		if (cache == null) {
			// File file = util.getFile(xmlDescription);
			String xml = util.readFromFile(file);
			Action action = actionCreator.getActionFromXML(xml);
			cache = new ActionCache();
			cache.setTimestamp(file.lastModified());
			aopManager.addAspects(action, handler, parameters);
			cache.getNode().setOriginal(action);
			actionCache.put(id, cache);
			clone = cache.getNode().getActionFromPool();
		} else {
			// if (util.isCacheValid(xmlDescription)) {
			if (file.lastModified() == cache.getTimestamp()) {
				clone = cache.getNode().getActionFromPool();
			} else {
				// File file = util.getFile(xmlDescription);
				String xml = util.readFromFile(file);
				Action action = actionCreator.getActionFromXML(xml);
				cache.setTimestamp(file.lastModified());
				aopManager.addAspects(action, handler, parameters);
				cache.getNode().setOriginal(action);
				cache.getNode().rebuild();
				clone = cache.getNode().getActionFromPool();
			}
		}

		// clone.setWorkArea(new WorkArea());

		return clone;

	}

	private String buildID(Handler handler, HandlerProcessParameters parameters) {
		String id = "";
		id += parameters.getApplication().getId();
		id += "-" + parameters.getApplication().getName();

		id += "-" + parameters.getModule().getId();
		id += "-" + parameters.getModule().getName();

		id += "-" + parameters.getResource().getId();
		id += "-" + parameters.getResource().getTargetUri();

		if (parameters.getHttpMethod() != null) {
			id += "-" + parameters.getHttpMethod().getId();
			id += "-" + parameters.getHttpMethod().getName();
		} else
			id += "-null-null";

		if (parameters.getMimeTypeHandler() != null) {
			id += "-" + parameters.getMimeTypeHandler().getId();
			id += "-" + parameters.getMimeTypeHandler().getMimeType();
		} else
			id += "-null-null";

		id += "-" + handler.getId();

		id += "-" + handler.getPath();

		return id;
	}

	public AOPManager getAopManager() {
		return aopManager;
	}

	public void setAopManager(AOPManager aopManager) {
		this.aopManager = aopManager;
	}

	public ActionCreator getActionCreator() {
		return actionCreator;
	}

	public void setActionCreator(ActionCreator actionCreator) {
		this.actionCreator = actionCreator;
	}

	public Map<String, ActionCache> getActionCache() {
		return actionCache;
	}

	public void setActionCache(Map<String, ActionCache> actionCache) {
		this.actionCache = actionCache;
	}

	public void clearCaches() {
		Collection<ActionCache> caches = actionCache.values();
		for (ActionCache actionCache : caches) {
			actionCache.getNode().dispose();
		}
		actionCache.clear();
	}
}
